package com.meng.system.config;

import com.meng.system.domain.ScheduledTask;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.config.CronTask;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
@Slf4j
public class CronTaskRegistrar implements DisposableBean {
 
    private final Map<Runnable, ScheduledTask> scheduledTasks = new ConcurrentHashMap<>(16);

    /**
     * 实现类为ThreadPoolTaskScheduler  在conf 中有配置bean
     */
    @Autowired
    private TaskScheduler taskScheduler;


    public TaskScheduler getScheduler() {
        return this.taskScheduler;
    }
 
    public void addCronTask(Runnable task, String cronExpression) {
        addCronTask(new CronTask(task, cronExpression));
    }

    /**
     * 任务添加
     * @param cronTask run和cron表达式
     */
    public void addCronTask(CronTask cronTask) {
        if (cronTask != null) {
            Runnable task = cronTask.getRunnable();
            //查看是否在当前任务池中执行，如果是 取消该任务
            if (this.scheduledTasks.containsKey(task)) {
                removeCronTask(task);
            }
            //map中进行管理
            this.scheduledTasks.put(task, scheduleCronTask(cronTask));
        }
    }

    /**
     * 移除任务池中的任务，并停止任务
     * @param task 任务对象
     */
    public void removeCronTask(Runnable task) {
        ScheduledTask scheduledTask = this.scheduledTasks.remove(task);
        if (scheduledTask != null) {
            scheduledTask.cancel();
        }
    }

    /**
     * 开启任务
     * @param cronTask 线程+cron
     * @return 返回任务操作类
     */
    public ScheduledTask scheduleCronTask(CronTask cronTask) {
        ScheduledTask scheduledTask = new ScheduledTask();
        //任务添加成功  scheduledTask 当前创建任务时的线程返回的 所以属于线程私有
        scheduledTask.future = this.taskScheduler.schedule(cronTask.getRunnable(), cronTask.getTrigger());
        return scheduledTask;
    }


    /**
     * 重写销毁 容器销毁 终止并清空全部job
     */
    @Override
    public void destroy() {
        for (ScheduledTask task : this.scheduledTasks.values()) {
            task.cancel();
        }
 
        this.scheduledTasks.clear();
    }
}